package com.xiaoshuidi.cloud.module.finance.service.finance.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xiaoshuidi.cloud.framework.common.core.KeyValue;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.kingdee.core.dto.TransferConfirmDTO;
import com.xiaoshuidi.cloud.framework.kingdee.core.dto.TransferConfirmResp;
import com.xiaoshuidi.cloud.framework.kingdee.core.service.KingdeeService;
import com.xiaoshuidi.cloud.framework.redis.sequence.TimebaseSequenceGenerator;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.module.contract.api.ContractOwnerOrderApi;
import com.xiaoshuidi.cloud.module.contract.vo.OwnerOrderTransferCallbackReqVO;
import com.xiaoshuidi.cloud.module.finance.api.finance.dto.BankTransferReqDTO;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.transfer.FinanceBankTransferPageReqVO;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.transfer.FinanceBankTransferPageResult;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.transfer.FinanceBankTransferReqVO;
import com.xiaoshuidi.cloud.module.finance.convert.finance.FinanceConvert;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.FinanceAccountWithdrawDO;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.FinanceBankTransferDO;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.FinancePaymentChangeLogDO;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.finance.FinanceAccountWithdrawMapper;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.finance.FinanceBankTransferMapper;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.finance.FinancePaymentChangeLogMapper;
import com.xiaoshuidi.cloud.module.finance.enums.ErrorCodeConstants;
import com.xiaoshuidi.cloud.module.finance.enums.finance.FinanceAccountWithdrawResultEnum;
import com.xiaoshuidi.cloud.module.finance.enums.finance.SourceBizTypeEnum;
import com.xiaoshuidi.cloud.module.finance.enums.order.BankTransferStatusEnum;
import com.xiaoshuidi.cloud.module.finance.enums.order.FinanceCommonStatusEnum;
import com.xiaoshuidi.cloud.module.finance.mq.producer.FinanceBankTransferProducer;
import com.xiaoshuidi.cloud.module.finance.service.finance.FinanceBankTransferService;
import com.xiaoshuidi.cloud.module.system.api.user.AdminUserApi;
import com.xiaoshuidi.cloud.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.xiaoshuidi.cloud.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.xiaoshuidi.cloud.module.finance.enums.ErrorCodeConstants.*;

@Slf4j
@Service
public class FinanceBankTransferServiceImpl implements FinanceBankTransferService {
    @Resource
    private FinanceBankTransferMapper financeBankTransferMapper;

    @Resource
    private FinanceAccountWithdrawMapper financeAccountWithdrawMapper;
    @Resource
    private KingdeeService kingdeeService;
    @Resource
    private TimebaseSequenceGenerator timebaseSequenceGenerator;
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private ContractOwnerOrderApi contractOwnerOrderApi;
    @Resource
    private FinanceBankTransferProducer financeBankTransferProducer;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Value("${spring.profiles.active}")
    private String profile;

    @Resource
    private FinancePaymentChangeLogMapper financePaymentChangeLogMapper;

    @Override
    public Integer save(BankTransferReqDTO reqDTO) {
        FinanceBankTransferDO financeBankTransferDO = FinanceConvert.INSTANCE.convert2(reqDTO);
        TransferConfirmDTO transferConfirmDTO = FinanceConvert.INSTANCE.convert(reqDTO);
        financeBankTransferDO.setDepartment(reqDTO.getDepartment());
        transferConfirmDTO.setDepartment(reqDTO.getDepartment());
        return save(transferConfirmDTO, financeBankTransferDO);
    }

    @Override
    public Integer save(FinanceBankTransferReqVO reqVO) {
        // 业主合同判断
        validateOwnerRentOut(reqVO.getBizNo(), reqVO.getBizType());
        FinanceBankTransferDO financeBankTransferDO = FinanceConvert.INSTANCE.convert3(reqVO);
        TransferConfirmDTO transferConfirmDTO = FinanceConvert.INSTANCE.convert(reqVO);
        return save(transferConfirmDTO, financeBankTransferDO);
    }

    //校验业主合同退租  有退租的业主账单无法付款
    void validateOwnerRentOut(String bizNo, String bizType) {
        // 业主账单
        if (SourceBizTypeEnum.OWNER_ORDER.name().equals(bizType) && org.apache.commons.lang3.StringUtils.isNotBlank(bizNo)) {
            CommonResult<Boolean> commonResult = contractOwnerOrderApi.ownerContractCheckRentOut(Long.valueOf(bizNo));
            log.info("查询业主账单是否可以付款，请求参数：{}，返回参数：{}", bizNo, commonResult);
            commonResult.checkError();
            if (commonResult.getData()) {
                throw new ServiceException(ErrorCodeConstants.FINANCE_BANK_TRANSFER_CREATE_FAILED_WITH_OWNER_RENT_OUT);
            }
        }
    }

    @Override
    public PageResult<FinanceBankTransferDO> getPage(FinanceBankTransferPageReqVO reqVO) {
        return financeBankTransferMapper.selectPage(reqVO);
    }

    @Override
    public FinanceBankTransferPageResult getFinanceBankTransferSummary(FinanceBankTransferPageReqVO reqVO) {
        List<Map<String, Object>> l = financeBankTransferMapper.selectConfirmSummary(reqVO);
        BigDecimal totalPaid = BigDecimal.ZERO;
        BigDecimal totalFailure = BigDecimal.ZERO;
        BigDecimal totalWaiting = BigDecimal.ZERO;
        int totalPaidCount = 0;
        int totalFailureCount = 0;
        int totalWaitingCount = 0;

        for (Map<String, Object> m : l) {
            Object status = m.get("status");
            Object payAmount = m.get("payAmount");
            Object count = m.get("cnt");
            if (FinanceCommonStatusEnum.SUCCESS.name().equals(status)) {
                totalPaid = new BigDecimal(payAmount.toString());
                totalPaidCount = Integer.parseInt(count.toString());
            } else if (FinanceCommonStatusEnum.WAITING.name().equals(status)) {
                totalWaiting = new BigDecimal(payAmount.toString());
                totalWaitingCount = Integer.parseInt(count.toString());
            } else if (FinanceCommonStatusEnum.FAILURE.name().equals(status)) {
                totalFailure = new BigDecimal(payAmount.toString());
                totalFailureCount = Integer.parseInt(count.toString());
            }
        }
        return FinanceBankTransferPageResult.builder().totalPaid(totalPaid)
                .totalPaidCount(totalPaidCount)
                .totalFailure(totalFailure)
                .totalFailureCount(totalFailureCount)
                .totalWaiting(totalWaiting)
                .totalWaitingCount(totalWaitingCount).build();
    }

    @Override
    public void update(Integer id, FinanceBankTransferReqVO reqVO) {
        FinanceBankTransferDO financeBankTransferDO = financeBankTransferMapper.selectById(id);
        if (financeBankTransferDO == null) {
            throw new ServiceException(ErrorCodeConstants.FINANCE_BANK_TRANSFER_NOT_EXISTS);
        }
        AdminUserRespDTO user;
        try {
            CommonResult<AdminUserRespDTO> loginUser = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId());
            loginUser.checkError();
            user = loginUser.getData();
        } catch (Exception e) {
            log.error("获取用户信息失败", e);
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }

        List<Object> logs = financeBankTransferDO.getLogs();
        if (CollectionUtils.isEmpty(logs)) {
            logs = new ArrayList<>(0);
        }
        String datetime = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        String logFmt = "%s(%s)编辑%s由\"%s\"修改为\"%s\"";
        if (StringUtils.hasText(reqVO.getPayeeName())
                && !Objects.equals(financeBankTransferDO.getPayeeName(), reqVO.getPayeeName())) {
            logs.add(new KeyValue<>(datetime, String.format(logFmt, user.getNickname(), user.getMobile(), "收款人", financeBankTransferDO.getPayeeName(),
                    reqVO.getPayeeName())));
        }
        if (StringUtils.hasText(reqVO.getPayeeBankAccount())
                && !Objects.equals(financeBankTransferDO.getPayeeBankAccount(), reqVO.getPayeeBankAccount())) {
            logs.add(new KeyValue<>(datetime, String.format(logFmt, user.getNickname(), user.getMobile(), "银行卡号", financeBankTransferDO.getPayeeBankAccount(),
                    reqVO.getPayeeBankAccount())));
        }
        if (StringUtils.hasText(reqVO.getPayeeBank())
                && !Objects.equals(financeBankTransferDO.getPayeeBank(), reqVO.getPayeeBank())) {
            logs.add(new KeyValue<>(datetime, String.format(logFmt, user.getNickname(), user.getMobile(), "所属银行", financeBankTransferDO.getPayeeBank(),
                    reqVO.getPayeeBank())));
        }
        if (StringUtils.hasText(reqVO.getPayeeBankBranch())
                && !Objects.equals(financeBankTransferDO.getPayeeBankBranch(), reqVO.getPayeeBankBranch())) {
            logs.add(new KeyValue<>(datetime, String.format(logFmt, user.getNickname(), user.getMobile(), "所属支行", financeBankTransferDO.getPayeeBankBranch(),
                    reqVO.getPayeeBankBranch())));
        }
        if (CollectionUtils.isEmpty(logs)) {
            logs.add(new KeyValue<>(datetime, String.format("%s(%s)重新提交", user.getNickname(), user.getMobile())));
        }
        String number = "FK" + timebaseSequenceGenerator.YYYYMMDDHHMMSS.next("lease:transfer:number", "%04d");
        logs.add(new KeyValue<>(datetime, String.format("%s(%s)重新提交, 原单号:%s", user.getNickname(), user.getMobile(), financeBankTransferDO.getNumber())));
        FinanceBankTransferDO.FinanceBankTransferDOBuilder update = FinanceBankTransferDO.builder()
                .id(id)
                .bizDate(LocalDate.now())
                .number(number)
                .payeeName(reqVO.getPayeeName())
                .payeeBankAccount(reqVO.getPayeeBankAccount())
                .payeeBank(reqVO.getPayeeBank())
                .payeeBankBranch(reqVO.getPayeeBankBranch())
                .payeeBankCode(reqVO.getPayeeBankCode())
                .payeeBankProvince(reqVO.getPayeeBankProvince())
                .payeeBankCity(reqVO.getPayeeBankCity())
                .isChange(null)
                .status(BankTransferStatusEnum.WAITING.name())
                .logs(logs);

        TransferConfirmDTO transferConfirmDTO = FinanceConvert.INSTANCE.convert(reqVO);
        transferConfirmDTO.setJbPerson(reqVO.getOperator());
        transferConfirmDTO.setBizDate(LocalDate.now().toString());
        transferConfirmDTO.setNumber(number);
        transferConfirmDTO.setDepartment(financeBankTransferDO.getDepartment());
        transferConfirmDTO.setCompany(financeBankTransferDO.getCompany());
        transferConfirmDTO.setYwlbNumber(financeBankTransferDO.getBusinessTypeNo());
        transferConfirmDTO.setMdNumber(financeBankTransferDO.getApartmentId() == null ? null : financeBankTransferDO.getApartmentId().toString());
        transferConfirmDTO.setBusinessScene(financeBankTransferDO.getBusinessType());
        transferConfirmDTO.setReason(financeBankTransferDO.getReason());

        try {
            paymentAccountProcessing(transferConfirmDTO);
            log.info("=====编辑后打款信息============{}",JSON.toJSONString(transferConfirmDTO));
            TransferConfirmResp resp = kingdeeService.transfer(transferConfirmDTO);
            if (!resp.isSuccess()) {
                logs.add(new KeyValue<>(datetime, String.format("推送失败: %s", resp.getMessage())));
                update.status(FinanceCommonStatusEnum.FAILURE.name());
                update.isChange(0);
            }
        } catch (Exception e) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), e.getMessage());
        }
        financeBankTransferMapper.updateById(update.build());
        //清除所有未处理更正记录
        financePaymentChangeLogMapper.update(null,new LambdaUpdateWrapper<FinancePaymentChangeLogDO>()
                .set(FinancePaymentChangeLogDO::getIsChange,null)
                .eq(FinancePaymentChangeLogDO::getIsChange,0)
                .eq(FinancePaymentChangeLogDO::getTransId,financeBankTransferDO.getId()));
        //失败生成一条记录
        if(update.build().getStatus().equals(FinanceCommonStatusEnum.FAILURE.name())){
            FinancePaymentChangeLogDO changeLogDO = FinanceConvert.INSTANCE.convertLogDo(update.build());
            changeLogDO.setId(null);
            changeLogDO.setTransId(financeBankTransferDO.getId().longValue());
            changeLogDO.setPayeeMobile(financeBankTransferDO.getPayeeMobile());
            changeLogDO.setBizNo(financeBankTransferDO.getBizNo());
            changeLogDO.setBizType(financeBankTransferDO.getBizType());
            changeLogDO.setCreateTime(null);
            changeLogDO.setIsChange(0);
            changeLogDO.setCreator(null);
            changeLogDO.setUpdater(null);
            changeLogDO.setUpdateTime(null);
            changeLogDO.setDeptId(financeBankTransferDO.getApartmentId());
            financePaymentChangeLogMapper.insert(changeLogDO);
        }
    }

    @Override
    public void payment(Integer id, FinanceBankTransferReqVO reqVO) {
        FinanceBankTransferDO financeBankTransferDO = financeBankTransferMapper.selectById(id);
        if (financeBankTransferDO == null) {
            throw new ServiceException(ErrorCodeConstants.FINANCE_BANK_TRANSFER_NOT_EXISTS);
        }

        AdminUserRespDTO user;
        try {
            CommonResult<AdminUserRespDTO> loginUser = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId());
            loginUser.checkError();
            user = loginUser.getData();
        } catch (Exception e) {
            log.error("获取用户信息失败", e);
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }
        TransferConfirmDTO transferConfirmDTO = FinanceConvert.INSTANCE.convert(financeBankTransferDO);
        transferConfirmDTO.setJbPerson(reqVO.getOperator());
        transferConfirmDTO.setBizDate(LocalDate.now().toString());
        transferConfirmDTO.setNumber(financeBankTransferDO.getNumber());
        transferConfirmDTO.setDepartment(financeBankTransferDO.getDepartment());
        transferConfirmDTO.setCompany(financeBankTransferDO.getCompany());
        transferConfirmDTO.setYwlbNumber(financeBankTransferDO.getBusinessTypeNo());
        transferConfirmDTO.setMdNumber(financeBankTransferDO.getApartmentId() == null ? null : financeBankTransferDO.getApartmentId().toString());
        transferConfirmDTO.setBusinessScene(financeBankTransferDO.getBusinessType());
        transferConfirmDTO.setReason(financeBankTransferDO.getReason());
        List<Object> logs = financeBankTransferDO.getLogs();
        if (null == logs){
            logs = new ArrayList<>();
        }
        String datetime = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        if (CollectionUtils.isEmpty(logs)) {
            logs.add(new KeyValue<>(datetime, String.format("%s(%s)提交付款", user.getNickname(), user.getMobile())));
        }
        FinanceBankTransferDO.FinanceBankTransferDOBuilder update = FinanceBankTransferDO.builder()
                .id(id)
                .status(BankTransferStatusEnum.WAITING.name())
                .isChange(null)
                .logs(logs);
        paymentAccountProcessing(transferConfirmDTO);
        // 非正式环境不推送
        if (!"prod".equals(profile)) {
            logs.add(new KeyValue<>(datetime, String.format("推送失败: %s", "测试环境不推送不进行打款")));
            update.status(FinanceCommonStatusEnum.FAILURE.name());
            update.isChange(0);
        }else{
            try {
                TransferConfirmResp resp = kingdeeService.transfer(transferConfirmDTO);
                if (!resp.isSuccess()) {
                    logs.add(new KeyValue<>(datetime, String.format("推送失败: %s", resp.getMessage())));
                    update.status(FinanceCommonStatusEnum.FAILURE.name());
                    update.isChange(0);
                }
            } catch (Exception e) {
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), e.getMessage());
            }
        }

        financeBankTransferMapper.updateById(update.build());
        //清除所有未处理更正记录
        failedFeedback(financeBankTransferDO,true);

    }

    @Override
    public FinanceBankTransferDO getById(Integer id) {
        return financeBankTransferMapper.selectById(id);
    }

    @Override
    public FinanceBankTransferDO getByBizNoAndBizType(String bizNo, String bizType) {
        return financeBankTransferMapper.selectOne(new QueryWrapper<FinanceBankTransferDO>()
                .eq("biz_no", bizNo)
                .eq("biz_type", bizType).last("limit 1"));
    }

    @Override
    public void saveBatch(List<BankTransferReqDTO> reqDTO) {
        if (CollectionUtils.isEmpty(reqDTO)) {
            return;
        }
        List<String> numbers = timebaseSequenceGenerator.YYYYMMDDHHMMSS.next("lease:transfer:number", reqDTO.size(), "%04d");
        List<FinanceBankTransferDO> financeBankTransferDOS = new ArrayList<>(reqDTO.size());
        for (int i = 0; i<reqDTO.size(); i++) {
            BankTransferReqDTO req = reqDTO.get(i);
            FinanceBankTransferDO financeBankTransferDO = FinanceConvert.INSTANCE.convert2(req);
            financeBankTransferDO.setBusinessTypeNo("ZCSQ");
            financeBankTransferDO.setBusinessType("自持社区");
            financeBankTransferDO.setCompany("合肥市住房租赁发展股份有限公司");
            if (!StringUtils.hasText(req.getNumber())) {
                financeBankTransferDO.setNumber("FK" + numbers.get(i));
            }
            financeBankTransferDO.setStatus("prod".equals(profile) ? BankTransferStatusEnum.WAITING.name() : BankTransferStatusEnum.FAILURE.name());
            financeBankTransferDOS.add(financeBankTransferDO);
        }
        transactionTemplate.executeWithoutResult(status -> financeBankTransferMapper.insertBatch(financeBankTransferDOS));
        // 正式环境才推送
        if ("prod".equals(profile)) {
            financeBankTransferProducer.send(financeBankTransferDOS.stream().map(FinanceBankTransferDO::getNumber).collect(Collectors.toList()));
        }
    }

    @Override
    public void send(String number) {
        FinanceBankTransferDO financeBankTransferDO = financeBankTransferMapper.selectOne("number", number);
        TransferConfirmDTO transferConfirmDTO = FinanceConvert.INSTANCE.convert(financeBankTransferDO);
        try {
            paymentAccountProcessing(transferConfirmDTO);
            TransferConfirmResp resp = kingdeeService.transfer(transferConfirmDTO);
            if (!resp.isSuccess()) {
                financeBankTransferDO.setStatus(FinanceCommonStatusEnum.FAILURE.name());
                financeBankTransferDO.setIsChange(0);
                if (CollectionUtils.isEmpty(financeBankTransferDO.getLogs())) {
                    financeBankTransferDO.setLogs(Collections.singletonList(new KeyValue<>(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), resp.getMessage())));
                }
                failedFeedback(financeBankTransferDO,true);
            }
        } catch (Exception e) {
            log.error("请求金蝶webservice接口异常", e);
            financeBankTransferDO.setStatus(FinanceCommonStatusEnum.FAILURE.name());
            if (CollectionUtils.isEmpty(financeBankTransferDO.getLogs())) {
                financeBankTransferDO.setLogs(Collections.singletonList(new KeyValue<>(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), "金蝶接口请求异常")));
            }
        }
        financeBankTransferMapper.updateById(FinanceBankTransferDO.builder()
                        .id(financeBankTransferDO.getId())
                        .status(financeBankTransferDO.getStatus())
                        .logs(financeBankTransferDO.getLogs())
                .build());

    }

    /**
     * 银行账号处理
     * @param transferConfirmDTO
     */
    private  void paymentAccountProcessing(TransferConfirmDTO transferConfirmDTO) {
        if(transferConfirmDTO != null){
            //收款名
            if(StrUtil.isNotBlank(transferConfirmDTO.getPayeeName())){
                transferConfirmDTO.setPayeeName(transferConfirmDTO.getPayeeName().replaceAll("\\s", ""));
            }
            //收款银行
            if(StrUtil.isNotBlank(transferConfirmDTO.getPayeeBank())){
                transferConfirmDTO.setPayeeBank(transferConfirmDTO.getPayeeBank().replaceAll("\\s", ""));
            }
            //收款账号
            if(StrUtil.isNotBlank(transferConfirmDTO.getPayeeBankAcct())){
                transferConfirmDTO.setPayeeBankAcct(transferConfirmDTO.getPayeeBankAcct().replaceAll("\\s", ""));
            }
            //收款银行行号
            if(StrUtil.isNotBlank(transferConfirmDTO.getPayeeBankCode())){
                transferConfirmDTO.setPayeeBankCode(transferConfirmDTO.getPayeeBankCode().replaceAll("\\s", ""));
            }

            log.info("=====处理后打款信息============{}",JSON.toJSONString(transferConfirmDTO));
        }
    }

    /**
     * 失败反馈记录
     * @param financeBankTransferDO
     * @param flag
     */
    private void failedFeedback(FinanceBankTransferDO financeBankTransferDO,Boolean flag) {
       try {
           if(flag){
               //清除所有未处理更正记录
               financePaymentChangeLogMapper.update(null,new LambdaUpdateWrapper<FinancePaymentChangeLogDO>()
                       .set(FinancePaymentChangeLogDO::getIsChange,null)
                       .eq(FinancePaymentChangeLogDO::getIsChange,0)
                       .eq(FinancePaymentChangeLogDO::getTransId, financeBankTransferDO.getId()));
           }
           //失败生成一条记录
           if(financeBankTransferDO.getStatus().equals(FinanceCommonStatusEnum.FAILURE.name())){
               FinancePaymentChangeLogDO changeLogDO = FinanceConvert.INSTANCE.convertLogDo(financeBankTransferDO);
               changeLogDO.setId(null);
               changeLogDO.setIsChange(0);
               changeLogDO.setTransId(financeBankTransferDO.getId().longValue());
               changeLogDO.setCreateTime(null);
               changeLogDO.setCreator(null);
               changeLogDO.setUpdater(null);
               changeLogDO.setUpdateTime(null);
               changeLogDO.setDeptId(financeBankTransferDO.getApartmentId());
               financePaymentChangeLogMapper.insert(changeLogDO);
           }
       }catch (Exception e){
           log.error("失败反馈log============{},={}", JSON.toJSONString(financeBankTransferDO),flag);
       }
    }

    private Integer save(TransferConfirmDTO transferConfirmDTO, FinanceBankTransferDO financeBankTransferDO) {
        log.info("department1:{},department2:{}",transferConfirmDTO.getDepartment(),financeBankTransferDO.getDepartment());
        if (!StringUtils.hasText(transferConfirmDTO.getNumber())) {
            transferConfirmDTO.setNumber("FK" + timebaseSequenceGenerator.YYYYMMDDHHMMSS.next("lease:transfer:number", "%04d"));
        }
        financeBankTransferDO.setBusinessTypeNo("ZCSQ");
        financeBankTransferDO.setBusinessType("自持社区");
        financeBankTransferDO.setCompany("合肥市住房租赁发展股份有限公司");
        financeBankTransferDO.setNumber(transferConfirmDTO.getNumber());
        financeBankTransferDO.setStatus(BankTransferStatusEnum.WAITING.name());
        transferConfirmDTO.setYwlbNumber(financeBankTransferDO.getBusinessTypeNo());
        transferConfirmDTO.setCompany(financeBankTransferDO.getCompany());
        transferConfirmDTO.setBusinessScene(financeBankTransferDO.getBusinessType());
        // 非正式环境不推送
        if (!"prod".equals(profile)) {
            financeBankTransferDO.setStatus(BankTransferStatusEnum.FAILURE.name());
            financeBankTransferDO.setIsChange(0);
            financeBankTransferMapper.insert(financeBankTransferDO);
            //第一次打款失败记录重置
            failedFeedback(financeBankTransferDO,false);
            return financeBankTransferDO.getId();
        }
        try {
            paymentAccountProcessing(transferConfirmDTO);
            TransferConfirmResp resp = kingdeeService.transfer(transferConfirmDTO);
            if (!resp.isSuccess()) {
                financeBankTransferDO.setStatus(FinanceCommonStatusEnum.FAILURE.name());
                financeBankTransferDO.setIsChange(0);
                financeBankTransferDO.setLogs(Collections.singletonList(new KeyValue<>(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), resp.getMessage())));
            }
        } catch (Exception e) {
            log.error("请求金蝶webservice接口异常", e);
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), e.getMessage());
        }
        financeBankTransferMapper.insert(financeBankTransferDO);
        //第一次打款失败记录重置
        failedFeedback(financeBankTransferDO,false);
        return financeBankTransferDO.getId();
    }

    @Override
    public FinanceBankTransferDO getByNumber(String number) {
        return financeBankTransferMapper.selectOne("number", number);
    }

    @Override
    @Transactional
    public void paySuccess(FinanceBankTransferDO financeBankTransferDO, String tradeSerialNo) {
        List<Object> logs = financeBankTransferDO.getLogs();
        if (CollectionUtils.isEmpty(logs)) {
            logs = new ArrayList<>();
        }
        logs.add(new KeyValue<>(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"),
                "付款成功" + tradeSerialNo));
         LocalDateTime now = LocalDateTime.now();
        financeBankTransferMapper.updateById(FinanceBankTransferDO.builder()
                .id(financeBankTransferDO.getId())
                .status(FinanceCommonStatusEnum.SUCCESS.name())
                .payTime(now)
                .logs(logs)
                .build());

        //清除所有未处理更正记录
        financePaymentChangeLogMapper.update(null,new LambdaUpdateWrapper<FinancePaymentChangeLogDO>()
                .set(FinancePaymentChangeLogDO::getIsChange,null)
                .eq(FinancePaymentChangeLogDO::getIsChange,0)
                .eq(FinancePaymentChangeLogDO::getTransId, financeBankTransferDO.getId()));

        if (SourceBizTypeEnum.OWNER_ORDER.name().equals(financeBankTransferDO.getBizType())) {
            OwnerOrderTransferCallbackReqVO reqVO = new OwnerOrderTransferCallbackReqVO();
            reqVO.setStatus(FinanceCommonStatusEnum.SUCCESS.name());
            reqVO.setPayTime(new Date());
            reqVO.setOrderNo(financeBankTransferDO.getBizNo());
            contractOwnerOrderApi.ownerTransferCallback(reqVO);
        }
        //修改余额状态为完成
        if (SourceBizTypeEnum.WITHDRAW.name().equals(financeBankTransferDO.getBizType())) {
            FinanceAccountWithdrawDO result =
                    FinanceAccountWithdrawDO.builder().id(Integer.valueOf(financeBankTransferDO.getBizNo()))
                            .result(FinanceAccountWithdrawResultEnum.SUCCESS.name()).payTime(now).build();
            financeAccountWithdrawMapper.updateById(result);
        }
    }

    /**
     * 批量付款
     *
     * @param ids
     */
    @Override
    public long paymentBatch(List<Long> ids) {
        log.info("打款ids=={}", ids);
        if (CollectionUtil.isEmpty(ids)) {
            throw exception(PAYMENT_BATCH_NULL_IDS);
        }
        if (ids.size() > 100) {
            throw exception(PAYMENT_BATCH_SIZE, 100);
        }
        List<FinanceBankTransferDO> financeBankTransferDOS =
                financeBankTransferMapper.selectList(FinanceBankTransferDO::getId, ids);
        if (CollectionUtil.isEmpty(financeBankTransferDOS)) {
            throw exception(PAYMENT_BATCH_NULL_DO);
        }

        log.info("打款dos=={}", financeBankTransferDOS);
        //查询未付款的
        List<FinanceBankTransferDO> collect =
                financeBankTransferDOS.stream().filter(f -> !BankTransferStatusEnum.SUCCESS.name().equals(f.getStatus())).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(financeBankTransferDOS)) {
            throw exception(PAYMENT_BATCH_EXIST_PAID);
        }
        long count = collect.size();
        for (FinanceBankTransferDO f : collect) {
            try {
                paySuccess(f, "");
            } catch (Exception e) {
                count--;
            }
        }
        return count;

    }

    @Override
    @Transactional
    public void payFailure(FinanceBankTransferDO financeBankTransferDO) {
        List<Object> logs = financeBankTransferDO.getLogs();
        if (CollectionUtils.isEmpty(logs)) {
            logs = new ArrayList<>();
        }
        logs.add(new KeyValue<>(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"),
                "付款失败"));
        financeBankTransferMapper.updateById(FinanceBankTransferDO.builder()
                .id(financeBankTransferDO.getId())
                .status(FinanceCommonStatusEnum.FAILURE.name())
                .isChange(0)
                .logs(logs)
                .build());
        FinancePaymentChangeLogDO changeLogDO = FinanceConvert.INSTANCE.convertLogDo(financeBankTransferDO);
            changeLogDO.setId(null);
            changeLogDO.setTransId(financeBankTransferDO.getId().longValue());
            changeLogDO.setIsChange(0);
            changeLogDO.setCreateTime(null);
            changeLogDO.setCreator(null);
            changeLogDO.setUpdater(null);
            changeLogDO.setUpdateTime(null);
            changeLogDO.setDeptId(financeBankTransferDO.getApartmentId());
            financePaymentChangeLogMapper.insert(changeLogDO);
        if (SourceBizTypeEnum.OWNER_ORDER.name().equals(financeBankTransferDO.getBizType())) {
            OwnerOrderTransferCallbackReqVO reqVO = new OwnerOrderTransferCallbackReqVO();
            reqVO.setStatus(FinanceCommonStatusEnum.FAILURE.name());
            reqVO.setOrderNo(financeBankTransferDO.getBizNo());
            contractOwnerOrderApi.ownerTransferCallback(reqVO);
        }
    }

    @Override
    public List<FinanceBankTransferDO> selectIds(List<Integer> ids) {
        List<FinanceBankTransferDO> financeBankTransferDOS =
                financeBankTransferMapper.selectList(FinanceBankTransferDO::getId, ids);
        return financeBankTransferDOS;
    }

    /**
     * 记录导出次数
     *
     * @param ids
     */
    @Override
    public void updateExportCount(List<Integer> ids) {
        financeBankTransferMapper.updateExportCount(ids);
    }
}
